#pragma once
#include <iostream>
#include <vector>
#include <queue>
#include <functional>
#include <unistd.h>
#include "thread.hpp"
#include "Log.hpp"
#include "Mutex.hpp"
#include "Cond.hpp"
//#include "Task.hpp"
namespace ThreadPoolModule
{
    using namespace ThreadModule;
    using namespace LogModule;
    using namespace MutexModule;
    using namespace CondModule;

    int default_thread_num = 5;
    template <class T>
    class ThreadPool
    {
        using task_t = T;
    public:
        static ThreadPool<T> *GetInstance()
        {
            if (instance == nullptr)
            {
                LockGuard lockguard(mutex);
                if (instance == nullptr)
                {
                    instance = new ThreadPool<T>();
                }
            }

            return instance;
        }

    private:
        ThreadPool(const ThreadPool<T> &tp) = delete; // 禁止拷贝构造
        const ThreadPool<T> &operator=(const ThreadPool<T> &tp) = delete;
        // 构造设为私有
        ThreadPool(int thread_num = default_thread_num)
            : _thread_num(thread_num),
              _is_running(false)
        {
            // 创建线程
            for (int i = 0; i < _thread_num; i++)
            {

                Thread t(std::bind(&ThreadPoolModule::ThreadPool<T>::HandlerTask, this, std::placeholders::_1));
                LOG(LogLevel::INFO) << "创建线程" << t.Name();
                _threads.push_back(t);
            }
        }
        bool IsEmpty()
        {
            return _task_q.empty();
        }
        void HandlerTask(std::string name)
        {
            while (true)
            {
                // 1.获取任务
                // 访问临界资源需要枷锁
                {
                    LockGuard lockguard(_mutex);
                    while (IsEmpty() && _is_running)
                    {
                        _wait_num++;
                        _cond.Wait(_mutex);
                        _wait_num--;
                    }
                    if (IsEmpty() && !_is_running)
                        break;
                }

                // 2. 处理任务
                // 是同步的可以不加锁，这样效率更高
                task_t t = _task_q.front();
                _task_q.pop();
                t(); // 这里规定传进来的任务对象需要重载（）来表示任务
            }
            LOG(LogLevel::INFO) << "回收线程" << name << "...成功";
        }

    public:
        ~ThreadPool()
        {
        }
        void Start()
        {
            if (_is_running)
                return;
            _is_running = true;
            for (auto &e : _threads)
            {
                LOG(LogLevel::INFO) << "启动线程" << e.Name();
                e.Start();
            }
        }
        void Wait()
        {
            for (auto &e : _threads)
            {
                e.Join();
                LOG(LogLevel::INFO) << "等待线程" << e.Name() << "...成功";
            }
        }
        void Stop()
        {
            if (!_is_running)
                return;
            _is_running = false;
            _cond.NotifyAll();
        }
        void Equeue(const task_t &t)
        {
            LOG(LogLevel::INFO) << "发送一个任务";
            LockGuard lockguard(_mutex);
            _task_q.push(t);
            if (_wait_num > 0)
                _cond.Notify();
        }

    private:
        bool _is_running;             // 线程池是否工作
        int _thread_num;              // 线程数量
        int _wait_num;                // 等待的线程数量
        std::vector<Thread> _threads; // 线程
        std::queue<task_t> _task_q;   // 任务队列
        Mutex _mutex;                 // 锁
        Cond _cond;
        static ThreadPool<T> *instance;
        static Mutex mutex;
    };
    template <class T>
    ThreadPool<T> *ThreadPool<T>::instance = nullptr;
    template <class T>
    Mutex ThreadPool<T>::mutex;

}
